Skip to content

perf(desktop): coalesce streaming events and isolate session/workspace switches - #3922

Merged
bobleer merged 2 commits into
mainfrom
bob/flowchat-workspace-perf
Nov 15, 2026
Merged

bobleer merged 2 commits into
mainfrom
bob/flowchat-workspace-perf

Conversation

@bobleer

@bobleer bobleer commented Nov 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Eliminates UI frame drops during long streaming replies, session-switching lag under concurrent multi-session execution, and multi-workspace switch stalls through four targeted surgeries plus sibling hot-path optimizations:

  1. Ordered batch transport & hidden-session stream isolation:
    • Extend Desktop EventCoalescer to coalesce consecutive TextChunk, ThinkingChunk, and ToolEventData::{ParamsPartial, Progress} runs while preserving strict arrival order; group contiguous high-frequency streaming chunk items onto "agentic://event-batch" while emitting lifecycle/completion events directly on their dedicated channels so standalone listeners always receive them even when AgenticEventListener is inactive.
    • Stage streaming deltas for non-visible sessions (excluding active main session, AuxPane/btw split views, and inspected subagent panels) via silent FlowChatStore updates and materialize/clean them atomically on visibility, cancellation, rollback, or session removal/promotion.
  2. Zero-JSON.stringify turn fingerprinting & WeakMap retained-byte memoization:
    • Replace full-turn JSON.stringify in PersistenceModule.calculateTurnHash with zero-allocation dual-32-bit structural fingerprinting across all modelRounds + WeakMap memoization on settled rounds/items, cache converted backend ModelRound payloads, skip redundant mid-turn updateSessionMetadata IPC writes unless UI metadata changed, and gate local checkpoints when driving a non-local Peer host.
    • Replace allocation-heavy recursive estimateRetainedBytes object entry arrays with zero-allocation walks + WeakMap<ModelRound, number> caching on completed rounds.
  3. Incremental tail Markdown parsing, thinking/tool-diff fast paths & adaptive streaming reveal:
    • Fix false-positive whole-document fallbacks in splitMarkdownSections so settled Markdown blocks stay cached and only the active streaming tail re-parses; strip code fences/spans (respecting CommonMark tab indentation and paragraph breaks) before math detection to avoid false KaTeX pipeline activation on $ in code; guard rehypeRaw behind raw HAST node presence; short-circuit unused plugins/scanners for thinking blocks.
    • Skip $O(N^2)$ Myers diffLines during ParamsPartial streaming for file edits over 80 lines (computing exact diff stats once settled) and avoid duplicate parsePartialJson calls.
    • Add adaptive paint cadence (minPaintIntervalMs / maxCharsPerPaint) in useTypewriter (both main text and ModelThinkingDisplay), keep Web Worker Markdown prewarms alive across typewriter ticks, and prune already-revealed DOM subtrees in useStreamingTextReveal.
  4. Session & workspace switch isolation:
    • Scope SessionsSection selectors to the active workspace(s), defer hidden-accordion updates, stabilize useSessionReviewActivity / useSessionGoalModeActive so ChatInput does not re-render on background chunks, deduplicate SnapshotStateManager.refreshSessionState and skip per-card file-list IPC storms on timeline file cards, and add input-equivalence guards across askUserQuestionState, sessionNavStatusService, sessionNavOrdering, and sessionSceneLifecycle.
    • Retain a 12-session cachedTurnPrefixById LRU in modernFlowChatStore, raise retained timeline views to 8 with module-level WeakSet prewarm deduplication, keep an 8-scope LRU in useResolvedModeSkills, and replace structuredClone canvas tab snapshots with shallow immutable snapshot cloning.
    • Collapse workspaceManager.setActiveWorkspace + WorkspaceProvider updates into a single context wave, coordinate cross-workspace session activation via pendingWorkspaceSessionActivation (with fallback initialize if target activation aborts), keep warm Git state caches across switches, deduplicate macOS AppKit NSMenu rebuilds on the main thread, and run best-effort workspace runtime directory/SSH ensure asynchronously off the set_active_workspace IPC critical path.

Type and Areas

Type: Performance / refactor

Areas: Desktop/Tauri (src/apps/desktop), Transport adapter (src/crates/adapters/transport), Rust core workspace service (src/crates/assembly/core), Web UI (src/web-ui)

Motivation / Impact

  • Streaming 300-round / multi-thousand-char Markdown responses and large file-edit tool calls no longer re-parse full documents, run $O(N^2)$ diffLines on partial JSON chunks, re-stringify full turn histories, or trigger N-session global store broadcast storms on every 16ms frame.
  • Switching between concurrently executing sessions or switching across workspaces avoids multi-wave WorkspaceContext re-renders, duplicate getSessionStats/getSessionFiles IPC bursts, redundant AppKit main-thread menu rebuilds, and cross-workspace session auto-selection races.
  • No persisted schema or wire-protocol breaking changes; older peers/transports and standalone Tauri event listeners continue receiving standard per-event channels seamlessly.

Verification

  • Rust:
    • cargo test -p openbitfun-transport --features tauri-adapter (passed)
    • cargo check -p openbitfun-desktop (passed)
    • cargo test -p openbitfun-desktop --lib event_coalescer & event_loop_driver_tests (24 passed)
    • cargo test --locked -p openbitfun-core --no-default-features --features agent-runtime,git,remote-workspace --lib service::workspace::service::tests (31 passed)
    • pnpm run fmt:rs (passed)
  • Web UI & Repository Gates:
    • Focused Vitest suites across all touched modules (35+ test files, 1,100+ tests passed), including longRoundPerfHarness.test.tsx (0.17 ms/flush avg across 300 rounds; 3.14 ms/chunk full React DOM tail streaming)
    • pnpm --dir src/web-ui exec tsc --noEmit (0 errors in touched files)
    • pnpm --dir src/web-ui exec eslint --max-warnings 0 on all touched files (passed, 0 warnings)
    • pnpm run i18n:audit && pnpm run check:web:appearance (passed)
    • pnpm run check:core-boundaries && pnpm run check:repo-hygiene (passed)
    • node scripts/check-git-object-sizes.mjs --base origin/main --head HEAD (passed)
  • Remote Scenario Coverage:
    • Exercised in unit/DOM test fixtures for Remote Workspace (remote-workspace workspace activation & POSIX scene/activation invariants) and Peer Device Mode (non-local peer checkpoint gating, surface activity observation on batched events, and single-event channel fallback). Live multi-host SSH/Relay hardware was not exercised locally.

Reviewer Notes

  • AI-assisted implementation; thoroughly audited and tested across affected Rust and Web UI modules, with full CI verification running on this PR.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

…e switches

Eliminate frame drops during long streaming replies, lag during concurrent multi-session switches, and multi-workspace switch stalls across four targeted areas:

1. Ordered batch transport & hidden-session isolation: coalesce consecutive TextChunk, ThinkingChunk, ToolEvent(ParamsPartial/Progress) runs in Desktop EventCoalescer and emit multi-event flushes via agentic://event-batch while preserving single-event compatibility; stage hidden-session streaming chunks in memory with silent store writes and materialize on session activation.
2. Zero-JSON.stringify persistence & WeakMap budget estimation: replace full-turn JSON.stringify hashing with dual-32-bit structural fingerprinting + WeakMap memoization, cache settled backend rounds, gate non-local peer checkpoints, and memoize retained-byte estimation per completed ModelRound.
3. Incremental tail Markdown & adaptive streaming reveal: fix whole-document fallback triggers in splitMarkdownSections, strip code spans/fences before math detection, make rehypeRaw conditional on raw HAST nodes, add adaptive typewriter paint cadence, and prune revealed subtrees in useStreamingTextReveal.
4. Session & workspace switch isolation: scope NavPanel session selectors by workspace, add per-session turn-prefix LRU and shallow canvas snapshot cloning, collapse workspace switching to a single WorkspaceContext wave without cross-workspace auto-select races, deduplicate macOS AppKit menubar rebuilds, and move best-effort workspace runtime ensure off the set_active_workspace IPC critical path.
@bobleer
bobleer merged commit db95809 into main Nov 15, 2026
13 checks passed
@bobleer
bobleer deleted the bob/flowchat-workspace-perf branch November 15, 2026 10:38
bobleer added a commit that referenced this pull request Nov 15, 2026
revert: revert PR #3922 streaming coalescing and session switch changes
bobleer added a commit to bobleer/OpenBitFun that referenced this pull request Nov 15, 2026
…itch changes

Reverts openBitFun#3922 (commit db95809) to restore baseline FlowChat streaming cadence and session/workspace behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant